package com.tfjybj.itoo.teach.provider.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.uuid.BaseUuidUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.teach.entity.BuildingEntity;
import com.tfjybj.itoo.teach.entity.RoomEntity;
import com.tfjybj.itoo.teach.model.RoomModel;
import com.tfjybj.itoo.teach.provider.dao.RoomDao;
import com.tfjybj.itoo.teach.provider.service.BuildingService;
import com.tfjybj.itoo.teach.provider.service.RoomService;
import com.tfjybj.itoo.teach.template.RoomExportTemplate;
import com.tfjybj.itoo.teach.template.RoomInfoTemplate;
import lombok.extern.slf4j.Slf4j;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.*;

import static com.tfjybj.itoo.teach.provider.until.DemoConstants.*;

@Slf4j
/**
 * RoomService接口实现类
 * ${base}表
 *
 * @author 田成荣
 * @version 2.0.0
 * @since 2.0.0 2018-11-08 19:34:10
 */
@Service("roomService")
public class RoomServiceImpl extends BaseServicePlusImpl<RoomDao, RoomEntity> implements RoomService {

    @Resource
    private RoomDao roomDao;

    @Resource
    private RedisTemplate<String, RoomInfoTemplate> redisTemplate;

    @Resource
    private BuildingService buildingService;
	 @Override
    public PageInfo<RoomEntity> queryByLikeCode(String code, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(roomDao.queryLikeCode(code));
    }

    /**
     * 根据建筑物ID查询所有可用的房间
     * @param buildingId
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-16 19:34:10
     */
    @Override
    public PageInfo<RoomModel> queryRoomByBuildingId(String buildingId, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<RoomModel>roomModelList=roomDao.queryRoomByBuildingId(buildingId);
        return new PageInfo<>(roomModelList);
    }

    /**
     * 根据最新十条房间信息
     * @param
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-18 19:34:10
     */
    @Override
    public List<RoomModel> queryNew10Rooms() {
        return roomDao.queryNew10Rooms();
    }

    /**
     * 根据Room名称Room类型模糊查询Room信息
     * @param roomName  房间名称
     * @param roomType  房间类型
     * @return roomModel
     * @author 段恩刚
     * @since 2.0.0 2018-11- 20 19:34:10
     */
    @Override
    public PageInfo<RoomModel> queryRoomsLikeNameOrType(String roomName, String roomType, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo,pageSize);
        List<RoomModel> roomModelList=roomDao.queryRoomsLikeNameOrType(roomName,roomType);
        return new PageInfo<>(roomModelList);
    }
    /**
     * 根据roomName导出room信息
     * @param roomName roomName
     * @param response response
     * @return 是否导出成功
     * @author 段恩刚
     * @since 1.0.0 2018-11-24 20:15:55
     */
    @Override
    public boolean exportRoomInfos(String roomName, HttpServletResponse response) {

        //获得要导出的fooList
        List<RoomModel> roomModels;
        if(("").equals(roomName)){
            roomModels=roomDao.queryAllRooms();
        }
        else {
            roomModels=roomDao.queryRoomsByLikeName(roomName);
        }

        List<RoomExportTemplate> roomExportTemplates=new ArrayList<>();

        for(RoomModel roomModel:roomModels){
            RoomExportTemplate roomExportTemplate=new RoomExportTemplate();
            BeanUtils.copyProperties(roomModel,roomExportTemplate);
            roomExportTemplate.setCode(roomModel.getCode());
            roomExportTemplate.setName(roomModel.getName());
            roomExportTemplate.setRoomType(roomModel.getRoomType());
            roomExportTemplate.setRoomCapacity(roomModel.getRoomCapacity());
            roomExportTemplate.setIsUsed(roomModel.getIsUsed());
            roomExportTemplates.add(roomExportTemplate);
        }
        //导出
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME, "房间信息");
        errorMap.put(SHEET_NAME, "房间信息");
        errorMap.put(TITLE, "房间信息");

        errorMap.put(COLUMNS, new String[]{"code", "name", "roomType", "roomCapacity", "isUsed"});
        errorMap.put(DATA_LIST, (Serializable) roomExportTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 根据Room类型查询Room信息
     * @param roomType  房间类型
     * @return <roomModel>list</roomModel>
     * @author 段恩刚
     * @since 2.0.0 2018-11- 27 19:34:10
     */
    @Override
    public List<RoomModel> queryRoomsbyType(String roomType) {

        return roomDao.queryRoomsbyType(roomType);
    }
    /**
     * 根据RoomId集合查询Room信息
     * @param roomIds 房间类型
     * @return <roomModel>list</roomModel>
     * @author 段恩刚
     * @since 2.0.0 2018-11- 27 19:34:10
     */
    @Override
    public List<RoomModel> queryRoomsbyIds(List<String> roomIds) {
        return roomDao.queryRoomsbyIds(roomIds);
    }

//    @Override
    /**
     * 下载房间信息模板，批量导入使用
     *
     * @param response 响应
     * @return 下载模板是否成功
     * @author 段恩刚
     * @since 2.0.0 2018-11-15 08:53:53
     **/
    @Override
    public boolean downLoadTemplate(HttpServletResponse response) {
        Map<Serializable, Serializable> map = new HashMap<>(16);
        List<RoomInfoTemplate> roomInfoTemplateList = new ArrayList<>();
        RoomInfoTemplate roomInfoTemplate=new RoomInfoTemplate();


        roomInfoTemplate.setCode("11666");
        roomInfoTemplate.setName("数理楼666教室");
        roomInfoTemplate.setRoomType("多媒体教室");
        roomInfoTemplate.setRoomCapacity(60);
        roomInfoTemplate.setIsUsed(0);
        roomInfoTemplate.setBuildingName("数理楼");
        roomInfoTemplateList.add(roomInfoTemplate);


        //sheet的名字
        map.put(SHEET_NAME, "房间信息");
        //需要导入的字段
        map.put(COLUMNS, new String[]{"code", "name", "roomType", "roomCapacity", "isUsed","buildingName"});
        //表格的标题
        map.put(TITLE, "房间信息");
        map.put(NAME, "房间信息");
        map.put(DATA_LIST, (Serializable) roomInfoTemplateList);

        try {
            ExcelUtil.exportExcel(map, response);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    /**
     * 判断导入的信息是否为空
     *
     * @param excelTPT 需要导入的信息
     * @return boolean 导入的字段是否为空
     * @author 段恩刚
     * @since 2.0.0 2018/11/16 20:43
     */
    private boolean verify(RoomInfoTemplate excelTPT )
    {
        if (StringUtils.isEmpty(excelTPT.getCode())) {
            excelTPT.setFailReason("房间代码未填写");
            log.warn("导入失败,建筑代码未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getName())) {
            excelTPT.setFailReason("房间名称未填写");
            log.warn("导入失败,房间名称未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getRoomType())) {
            excelTPT.setFailReason("房间类型未填写");
            log.warn("导入失败,建筑未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getRoomCapacity() )) {
            excelTPT.setFailReason("房间容量未填写");
            log.warn("导入失败,房间容量未填写未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getIsUsed())) {
            excelTPT.setFailReason("是否被占用未填写");
            log.warn("导入失败,是否被占用未填写,excelFooEntity-{}", excelTPT);
            return false;
        }

        if (StringUtils.isEmpty(excelTPT.getBuildingName())) {
            excelTPT.setFailReason("所属建筑名称未填写");
            log.warn("导入失败,所属建筑名称未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        //判断房间信息是否已经存在
        String roomName=excelTPT.getName();
        String roomCode=excelTPT.getCode();
        String idIsExist=roomDao.findIdIsExist(roomName,roomCode);
        if (!StringUtils.isEmpty(idIsExist)) {
            excelTPT.setFailReason("房间名称或者房间Code重复");
            log.warn("导入失败,房间名称或者房间Code重复,excelFooEntity-{}", excelTPT);
            return false;
        }
        //判断房间所属建筑Id是否存在
        String buildingId= buildingService.queryBuildingIdByName(excelTPT.getBuildingName());
        if (StringUtils.isEmpty(buildingId)) {
            excelTPT.setFailReason("房间所属建筑名称不存在");
            log.warn("导入失败,房间所属建筑名称不存在,excelFooEntity-{}", excelTPT);
            return false;
        }
        return true;
    }
    /**
     * 批量导入
     * @param
     * @return
     * @author 段恩刚
     * @since 2.0.0 2018/11/26 14:29
     */
    @Override
    public ItooResult importTemplate(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("UTF-8");
        try {
            //检验文件是否存在
            String fileName=multipartFile.getOriginalFilename();
            if (fileName==null){
                log.error("导入失败,fileName is null!");
                return ItooResult.build(ItooResult.FAIL, "传入的文件为空！");
            }
            //EXCEL解析成List
            Map<Serializable, Serializable> map = new HashMap<>(4);
            map.put(SHEET_NAME, "房间信息");
            map.put(CLASS, RoomInfoTemplate.class);

            List<RoomInfoTemplate> roomInfoTemplateList= ExcelUtil.importExcel(Objects.requireNonNull(fileName), map, request, response);

            if (roomInfoTemplateList.size() == 0) {
                return ItooResult.build(ItooResult.FAIL, "导入的数据为空，请填写！");
            }
            //定义导入的错误数据集合并存redis中形式的<String,TrainingProgramsTemplate>
            List<RoomInfoTemplate> errorTPTList = new ArrayList<>();
            String errorTPTListId = BaseUuidUtils.base58Uuid();
            Long size = redisTemplate.opsForZSet().size(errorTPTListId);
            size = size == null ? 0L : size;

            for(RoomInfoTemplate excelTPT:roomInfoTemplateList){

                if(!this.verify(excelTPT)){
                    RoomInfoTemplate roomInfoTemplateT=new RoomInfoTemplate();
                    BeanUtils.copyProperties(excelTPT,roomInfoTemplateT);

                    errorTPTList.add(roomInfoTemplateT);
                    redisTemplate.opsForZSet().add(errorTPTListId,roomInfoTemplateT,size+1);
                    continue;
                }


                RoomEntity roomEntity=new RoomEntity();

                //将导入内容放到entity中对应的属性中去
                BeanUtils.copyProperties(excelTPT,roomEntity);

                //建筑信息的id
                roomEntity.setId(IdWorker.getIdStr());
                //建筑未删除
                roomEntity.setIsDelete(0);

                roomEntity.setCode(excelTPT.getCode());
                roomEntity.setName(excelTPT.getName());
                roomEntity.setRoomType(excelTPT.getRoomType());
                roomEntity.setRoomCapacity(excelTPT.getRoomCapacity());
                roomEntity.setIsUsed(excelTPT.getIsUsed());

                //根据建筑的名字获取建筑的Id,作为房间所属的建筑的Id
                String buildingId= buildingService.queryBuildingIdByName(excelTPT.getBuildingName());
                roomEntity.setBuildingId(buildingId);

                this.save(roomEntity);
            }

            // 不符合条件的信息返回
            if (errorTPTList.size() > 0) {
                return ItooResult.build("0001","部分导入失败",errorTPTListId);
            }

        }
        catch (Exception e){
            return ItooResult.build(ItooResult.FAIL, "导入数据异常！",e);
        }
        return ItooResult.build(ItooResult.FAIL, "导入数据成功！");
    }

    /**
     * 导出错误数据
     *
     * @param response 响应
     * @param errorListId 为成功导入的分组id
     * @return 房间信息model
     * @author 段恩刚
     * @since 2018年11月30日11:32:54
     */
    @Override
    public boolean downErrorList(String errorListId, HttpServletResponse response) {
        // redis 取出没有成功导入的人员信息
        Set set = redisTemplate.opsForZSet().range(errorListId,0,-1);
        List<RoomExportTemplate> roomExportTemplates=new ArrayList<>(set);

        // 清空redis数据
        redisTemplate.delete(errorListId);

        //导出
        if (roomExportTemplates.size() == 0){
            return false;
        }
        Map<Serializable,Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME,"未导入的信息");
        errorMap.put(SHEET_NAME,"房间信息");
        errorMap.put(TITLE,"未导入的信息");
        errorMap.put(COLUMNS,new String[]{"code", "name", "roomType", "roomCapacity", "isUsed","buildingName","failReason"});
        errorMap.put(DATA_LIST,(Serializable) roomExportTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        }catch (Exception e ){
            return false;
        }
        return true;
    }

    /**
     * 根据房间code和房间名称判断建筑是否已经存在
     * @param roomCode 房间code
     * @param roomName 房间名称
     * @return 建筑id
     * @author 段恩刚
     * @since 2.0.0 2018/11/27 19:19
     * */
    @Override
    public String findIdIsExist(String roomName, String roomCode) {
        return roomDao.findIdIsExist(roomName,roomCode);
    }

    /**
     * 根据房间名称模糊查询房间信息
     * @param roomName  建筑名称
     * @param pageNo   页码
     * @param pageSize 页数
     * @return roomModel
     * @author 段恩刚
     * @since 2018年12月15日19:44:31
     */
    @Override
    public PageInfo<RoomModel> queryRoomsByLikeName(String roomName, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<RoomModel>roomModelList=roomDao.queryRoomsByLikeName(roomName);
        return new PageInfo<>(roomModelList);
    }

    /**
     * 根据房间名称和建筑Id分页模糊查询房间信息
     * @param roomName  房间名称
     * @param buildingId
     * @param pageNo   页码
     * @param pageSize 页数
     * @return roomModel
     * @author 段恩刚
     * @since 2018年12月15日19:44:31
     */
    @Override
    public PageInfo<RoomModel> queryRoomsByLikeNameAndBuildingId(String roomName, String buildingId, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo,pageSize);
        List<RoomModel> roomModelList=roomDao.queryRoomsByLikeNameAndBuildingId(roomName, buildingId);
        return new PageInfo<>(roomModelList);
    }

    @Override
    public List<RoomEntity> findByBuildingId(String buildingId) {
        return roomDao.findByBuildingId(buildingId);
    }

    @Override
    public List<RoomEntity> findByRoomId(String roomId) {
        return roomDao.findByRoomId(roomId);
    }

    @Override
    public List<RoomEntity> findComputerRoom(Object schoolBranch) {
//        List<BuildingEntity> buildingEntityList = buildingService.findBuilding();
        //todo 调用其他service的接口
        List<BuildingEntity> buildingEntityList =new ArrayList<>();
        List<RoomEntity> roomEntityList = new ArrayList<>();
        List<String> buildingIdArrayList = getBuildList(buildingEntityList,schoolBranch);
        for (Object buildingId : buildingIdArrayList) {
            roomEntityList.addAll(roomDao.findComputerRoom(buildingId));
        }
        return roomEntityList;
    }

    @Override
    public PageInfo<RoomEntity> findRoom(String searchInfo, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        return new PageInfo<>(roomDao.findRoom(searchInfo));
    }

    @Override
    public List<RoomEntity> queryNoExamRoom(String schoolCode, String startTime) {
//        List<BuildingEntity> buildingEntityList = buildingService.findBuilding();
        //todo 调用其他service
        List<BuildingEntity> buildingEntityList = new ArrayList<>();
        List<RoomEntity> roomList = new ArrayList<>();
        ArrayList<String> buildingList =getBuildList(buildingEntityList,schoolCode);
        for (Object buildingId : buildingList) {
            roomList.addAll(roomDao.queryNoExamRoom(buildingId, startTime));
        }
        return roomList;
    }

    /**
     * 判断schoolCode是否满足条件
     * @param buildingEntityList
     * @return
     */
    public ArrayList<String> getBuildList(List<BuildingEntity> buildingEntityList, Object schoolCode){
        ArrayList<String> buildingList = new ArrayList<>();
        for (BuildingEntity schoolCodeNumber : buildingEntityList) {
            if ("011".equals(schoolCodeNumber.getSchoolBranch()) && "011".equals(schoolCode)) {
                buildingList.add(schoolCodeNumber.getId());
            } else if ("010".equals(schoolCodeNumber.getSchoolBranch()) && "010".equals(schoolCode)) {
                buildingList.add(schoolCodeNumber.getId());
            }
        }
        return buildingList;
    }

    @Override
    public List<RoomModel> selNotExamRoom(String fuzzyValue, String schoolKey, String startTime, String endTime) {
        return roomDao.selNotRoom(fuzzyValue, schoolKey, startTime, endTime);
    }

    @Override
    public List<RoomModel> selNotRoom(String schoolKey, String startTime, String endTime) {
        /**
         * 分成两部分查找,减少考场座位的浪费
         * 1.调取教务的room表查询没有安排的所有考场
         * 2.查询examRoom表中没有安排完座位的考场,(还有剩余座位的考场)
         */
        // 查询所有没有安排过的考场
        return roomDao.selNotRoom("", schoolKey, startTime, endTime);
    }
}
